package com.fzy.core.codetools;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.fzy.core.system.entity.Entity;
import com.fzy.core.system.entity.Mapping;
import com.fzy.core.system.entity.Module;
import com.fzy.core.system.entity.Property;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class Generator {
	private static final Log log = LogFactory.getLog(Generator.class);
	private static String propertyType;

	public static void start() {
		writeMapping("test.ftl", "test.txt", "");
	}

	public static void writeMapping(String templateName, String fileName,
			String path) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);
		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		Map data = new HashMap();
		data.put("mapping", m);
		data.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
		String out = produce(freemarkerEngine, templateName, data);
		String outPath = (String) p.get("path.out.dir");
		write(out, fileName, classPath + "../" + outPath + path);
	}

	public static void writeMappingFromDb(String templateName, String fileName,
			String path, String[] tables, String moduleName, String moduleTitle) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = db2mapping(tables, moduleName, moduleTitle);
		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		Map data = new HashMap();
		data.put("mapping", m);
		data.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
		String out = produce(freemarkerEngine, templateName, data);
		String outPath = (String) p.get("path.out.dir");
		write(out, fileName, classPath + "../" + outPath + path);
	}

	public static void writeEntity(String templateName, String fileName,
			String prefixPackage, String path) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);

		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		String outPath = (String) p.get("path.out.dir");

		for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();) {
			ModuleWrapper o = (ModuleWrapper) iterator.next();
			for (Iterator iterator2 = o.getEntities().iterator(); iterator2
					.hasNext();) {
				EntityWrapper e = (EntityWrapper) iterator2.next();
				Map data = new HashMap();
				data.put("entity", e);
				data.put("statics", BeansWrapper.getDefaultInstance()
						.getStaticModels());
				data.put("prefixPackage", prefixPackage);
				String out = produce(freemarkerEngine, templateName, data);
				write(out, e.getNameCapital() + fileName, classPath + "../"
						+ outPath + path + "/" + e.getPath() + "/"
						+ prefixPackage);
			}
		}

	}

	public static void writeEntityHasId(String templateName, String fileName,
			String prefixPackage, String path) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);

		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		String outPath = (String) p.get("path.out.dir");

		for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();) {
			ModuleWrapper o = (ModuleWrapper) iterator.next();
			for (Iterator iterator2 = o.getEntities().iterator(); iterator2
					.hasNext();) {
				EntityWrapper e = (EntityWrapper) iterator2.next();
				if(!e.getHasId()) continue;
				Map data = new HashMap();
				data.put("entity", e);
				data.put("statics", BeansWrapper.getDefaultInstance()
						.getStaticModels());
				data.put("prefixPackage", prefixPackage);
				String out = produce(freemarkerEngine, templateName, data);
				write(out, e.getNameCapital() + fileName, classPath + "../"
						+ outPath + path + "/" + e.getPath() + "/"
						+ prefixPackage);
			}
		}

	}

	public static void writeCompositeId(String templateName, String fileName,
			String prefixPackage, String path) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);

		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		String outPath = (String) p.get("path.out.dir");

		for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();) {
			ModuleWrapper o = (ModuleWrapper) iterator.next();
			for (Iterator iterator2 = o.getEntities().iterator(); iterator2
					.hasNext();) {
				EntityWrapper e = (EntityWrapper) iterator2.next();
				if(!e.getHasCompositeId()) continue;
				Map data = new HashMap();
				data.put("entity", e);
				data.put("statics", BeansWrapper.getDefaultInstance()
						.getStaticModels());
				data.put("prefixPackage", prefixPackage);
				String out = produce(freemarkerEngine, templateName, data);
				write(out, e.getNameCapital() + fileName, classPath + "../"
						+ outPath + path + "/" + e.getPath() + "/"
						+ prefixPackage);
			}
		}

	}

	public static void writeJsp(String templateName, String fileName) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);

		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		String outPath = (String) p.get("path.out.dir");

		for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();) {
			ModuleWrapper o = (ModuleWrapper) iterator.next();
			for (Iterator iterator2 = o.getEntities().iterator(); iterator2
					.hasNext();) {
				EntityWrapper e = (EntityWrapper) iterator2.next();
				Map data = new HashMap();
				data.put("entity", e);
				data.put("statics", BeansWrapper.getDefaultInstance()
						.getStaticModels());
				String out = produce(freemarkerEngine, templateName, data);
				write(out, e.getNameUncapital() + fileName, classPath + "../"
						+ outPath + "/WebRoot/WEB-INF/jsp/ge/" + e.getModuleName());
			}
		}

	}

	public static void writeModule(String templateName, String fileName,
			String path) {
		Properties p = getProperties(null);
		String srcPath = (String) p.get("path.xml.src");
		String classPath = getClassPath();
		Document d = file2doc(new File(classPath + srcPath));
		MappingWrapper m = doc2mapping(d);

		String templatePath = (String) p.get("path.template.dir");
		Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
		String outPath = (String) p.get("path.out.dir");

		for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();) {
			ModuleWrapper o = (ModuleWrapper) iterator.next();
			Map data = new HashMap();
			data.put("module", o);
			data.put("statics", BeansWrapper.getDefaultInstance()
					.getStaticModels());
			String out = produce(freemarkerEngine, templateName, data);
			write(out, fileName + o.getName() + ".xml", classPath + "../"
					+ outPath + path);
		}

	}

	//
	// public static void writeEntitiesFromDb(String templateName,
	// String fileName, String prefixPackage, String path,
	// String[] tables, String moduleName, String moduleTitle) {
	// Properties p = getProperties(null);
	// String srcPath = (String) p.get("path.xml.src");
	// String classPath = getClassPath();
	// MappingWrapper m = db2mapping(tables, moduleName, moduleName);
	//
	// String templatePath = (String) p.get("path.template.dir");
	// Configuration freemarkerEngine = getFreemarkerEngine(templatePath);
	// String outPath = (String) p.get("path.out.dir");
	//
	// for (Iterator iterator = m.getModules().iterator(); iterator.hasNext();)
	// {
	// ModuleWrapper o = (ModuleWrapper) iterator.next();
	// for (Iterator iterator2 = o.getEntities().iterator(); iterator2
	// .hasNext();) {
	// EntityWrapper e = (EntityWrapper) iterator2.next();
	// Map data = new HashMap();
	// data.put("entity", e);
	// data.put("statics", BeansWrapper.getDefaultInstance()
	// .getStaticModels());
	// data.put("prefixPackage", prefixPackage);
	// String out = produce(freemarkerEngine, templateName, data);
	// write(out, e.getNameCapital() + fileName, classPath + "../"
	// + outPath + path + "/" + e.getPath() + "/"
	// + prefixPackage);
	// }
	// }
	// }

	public static DocumentBuilder getDocumentBuilder() {
		return DocumentBuilderHolder.documentBuilder;
	}

	public static String getClassPath() {
		return Generator.class.getClassLoader().getResource(".").getPath();
	}

	public static Properties getProperties(String propertiesPath) {
		if (StringUtils.isBlank(propertiesPath))
			propertiesPath = "application.properties";
		String classPath = getClassPath();
		File f = new File(classPath + propertiesPath);
		Properties p = new Properties();
		if (f.canRead())
			try {
				p.load(new FileInputStream(f));
			} catch (FileNotFoundException e) {
				log.error(e.getMessage(), e);
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
		return p;
	}

	public static Configuration getFreemarkerEngine(String templatePath) {
		if (StringUtils.isBlank(templatePath))
			templatePath = "/template";
		templatePath = templatePath.trim();
		Configuration freemarkerEngine = new Configuration();
		freemarkerEngine.setDefaultEncoding("UTF-8");
		TemplateLoader l = new ClassTemplateLoader(Generator.class,
				templatePath);
		freemarkerEngine.setTemplateLoader(l);
		return freemarkerEngine;
	}

	public static String produce(Configuration freemarkerEngine,
			String templateName, Object data) {
		StringWriter tempWriter = new StringWriter();
		BufferedWriter bw = new BufferedWriter(tempWriter);
		Template t;
		try {
			t = freemarkerEngine.getTemplate(templateName);
			t.process(data, bw);
		} catch (TemplateException e) {
			log.error(e.getMessage(), e);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		try {
			bw.flush();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			throw new RuntimeException("Error while flushing to string", e);
		}
		return tempWriter.toString();
	}

	public static void write(String content, String fileName, String path) {
		File f = new File(path);
		if (!f.exists())
			f.mkdirs();
		OutputStreamWriter fw = null;
		try {
			fw = new OutputStreamWriter(new FileOutputStream(new File(path,
					fileName)), "UTF-8");
			fw.write(content);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} finally {
			if (fw != null) {
				try {
					fw.flush();
					fw.close();
				} catch (IOException e) {
					log.error(e.getMessage(), e);
				}
			}
		}
	}

	public static Document file2doc(File file) {
		Document result = null;
		try {
			result = getDocumentBuilder().parse(file);
		} catch (SAXException e) {
			log.error(e.getMessage(), e);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		return result;
	}

	public static MappingWrapper db2mapping(String[] tables, String moduleName,
			String moduleTitle) {
		Mapping mapping = new Mapping();
		MappingWrapper result = new MappingWrapper();
		result.setData(mapping);

		Module module = new Module();
		module.setName(moduleName);
		module.setTitle(moduleTitle);
		ModuleWrapper moduleWrapper = new ModuleWrapper();
		moduleWrapper.setData(module);
		moduleWrapper.setParent(result);

		appendEntitiesFromDb(moduleWrapper, tables);

		List moduleList = new LinkedList();
		moduleList.add(moduleWrapper);
		result.setModules(moduleList);

		return result;
	}

	private static void appendEntitiesFromDb(ModuleWrapper moduleWrapper,
			String[] tables) {
		Dbo dbo = new Dbo();

		List objList = new LinkedList();
		for (int i = 0; i < tables.length; i++) {
			String table = tables[i];
			
			String sql = "";
			sql += " select * from ALL_TAB_COMMENTS where table_name = upper('"+table+"')";
			ResultSet rs = dbo.query(sql);
			Entity o = new Entity();
			EntityWrapper w = new EntityWrapper();
			try {
				while (rs.next()) {
					table = table.toLowerCase();
					o.setName(table);
					o.setTableName(table);
					String comment = StringUtils.defaultString(rs.getString("comments"));
					comment = comment.replaceAll("\\s", " ");
					comment = Utils.escapeXml(comment);
					o.setComment(comment);
					o.setTitle(StringUtils.isBlank(comment) ? table : comment);
					o.setIsAuto("false");
				}
				appendPropertiesFromDb(w, table);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			w.setData(o);
			w.setParent(moduleWrapper);
			objList.add(w);
		}
		dbo.close();
		moduleWrapper.setEntities(objList);
	}

	private static void appendPropertiesFromDb(EntityWrapper entityWrapper,
			String table) throws SQLException {
		Dbo dbo = new Dbo();
		String sql = "";

		sql += " select z.*,b.r_table_name,b.r_column_name , nvl(a.isp,0)+nvl(b.isp,0) isp,nvl(a.isr,0)+nvl(b.isr,0)isr,nvl(a.isu,0)+nvl(b.isu,0)isu";
		sql += " from";
		sql += " ( select a.*, b.comments from";
		sql += "  (select table_name,column_name,data_type,data_length,data_precision,data_scale,nullable,column_id from all_tab_columns where table_name = upper('"+table+"') order by column_id) a left join";
		sql += "  (select table_name,column_name,comments from ALL_COL_COMMENTS where table_name = upper('"+table+"')) b on a.table_name = b.table_name and a.column_name = b.column_name";
		sql += " ) z,(";
		sql += " SELECT cols.table_name, cols.column_name, cols2.table_name r_table_name, cols2.column_name r_column_name, decode(cons.constraint_type,'P',1,0) isP, decode(cons.constraint_type,'R',1,0) isR, decode(cons.constraint_type,'U',1,0) isU";
		sql += " FROM all_constraints cons left join all_cons_columns cols on cons.constraint_name = cols.constraint_name and cons.owner = cols.owner";
		sql += "  left join all_cons_columns cols2 on cons.r_constraint_name = cols2.constraint_name and cons.r_owner = cols2.owner";
		sql += " WHERE cols.table_name = upper('"+table+"')";
		sql += " AND cons.constraint_type in ('R', 'P', 'U')";
		sql += " and cons.status = 'ENABLED'";
		sql += " and cols2.table_name is null";
		sql += " ORDER BY cols.table_name, cols.position)a,(";
		sql += " SELECT cols.table_name, cols.column_name, cols2.table_name r_table_name, cols2.column_name r_column_name, decode(cons.constraint_type,'P',1,0) isP, decode(cons.constraint_type,'R',1,0) isR, decode(cons.constraint_type,'U',1,0) isU";
		sql += " FROM all_constraints cons left join all_cons_columns cols on cons.constraint_name = cols.constraint_name and cons.owner = cols.owner";
		sql += "  left join all_cons_columns cols2 on cons.r_constraint_name = cols2.constraint_name and cons.r_owner = cols2.owner";
		sql += " WHERE cols.table_name = upper('"+table+"')";
		sql += " AND cons.constraint_type in ('R', 'P', 'U')";
		sql += " and cons.status = 'ENABLED'";
		sql += " and cols2.table_name is not null";
		sql += " ORDER BY cols.table_name, cols.position)b";
		sql += " where  z.table_name=a.table_name(+) and z.column_name = a.column_name(+)";
		sql += " and z.table_name = b.table_name(+) and z.column_name = b.column_Name(+)";
		sql += " order by z.column_id";
		ResultSet rs = dbo.query(sql);

		List objList = new LinkedList();
		int countKey = 0;
		while (rs.next()) {
			Property o = new Property();
			int scale = Utils.string2int(rs.getString("data_scale"), 0);
			String type = dbType2propertyType(rs.getString("data_type"), scale);
			String columnName = rs.getString("column_name").toLowerCase(); 
			o.setName(columnName);
			o.setColumnName(columnName);
			String comment = StringUtils.defaultString(rs.getString("comments"));
			comment = comment.replaceAll("\\s", " ");
			comment = Utils.escapeXml(comment);
			o.setComment(comment);
//			o.setDefaultValue("");
			if(PropertyWrapper.STRING.equalsIgnoreCase(type)){
				o.setLength(rs.getString("data_length"));
			}else{
				o.setPropertyType(type);
			}
			boolean isKey = "1".equalsIgnoreCase(rs.getString("isp"));
			if(isKey){
				countKey++ ;
				o.setIsNotNull(null);
			}else{
				o.setIsNotNull("N".equalsIgnoreCase(rs.getString("nullable")) ? "true"
						: null);
			}
			o.setIsKey(isKey ? "true"
					: null);
			if(PropertyWrapper.NUMBER.equalsIgnoreCase(type)){
				o.setPrecision(rs.getString("data_precision"));
				o.setScale(scale + "");
			}
			String title = StringUtils.isBlank(comment) ? columnName : comment;
			int firstParentheses = title.indexOf("(");
			if(firstParentheses > -1){
				title = title.substring(0, firstParentheses);
			}
			o.setTitle(title);
			boolean isR = "1".equalsIgnoreCase(rs.getString("isr"));
			if(isR){
				o.setRefTable(rs.getString("r_table_name").toLowerCase());
				o.setRefColumn(rs.getString("r_column_name").toLowerCase());
			}
			o.setIsUnique("1".equalsIgnoreCase(rs.getString("isu")) ? "true"
					: null);

			PropertyWrapper w = new PropertyWrapper();
			w.setData(o);
			w.setParent(entityWrapper);
			objList.add(w);
		}
		dbo.close();
		//有唯一主键，则命名为ID
		if(countKey == 1){
			for (Iterator iterator = objList.iterator(); iterator.hasNext();) {
				PropertyWrapper p = (PropertyWrapper) iterator.next();
				if(p.getIsKey()){
					p.getData().setName("id");
				}
			}
		}
		entityWrapper.setProperties(objList);
	}

	private static String dbType2propertyType(String dbType, int scale) {
		String result = "";
		if ("VARCHAR2".equalsIgnoreCase(dbType)) {
			result = PropertyWrapper.STRING;
		}
		if ("NUMBER".equalsIgnoreCase(dbType)) {
			if(scale < 1)
				result = PropertyWrapper.LONG;
			else
				result = PropertyWrapper.NUMBER;
		}
		if ("DATE".equalsIgnoreCase(dbType)) {
			result = PropertyWrapper.DATE;
		}
		if ("CHAR".equalsIgnoreCase(dbType)) {
			result = PropertyWrapper.STRING;
		}
		return result;
	}

	public static MappingWrapper doc2mapping(Document document) {
		Mapping mapping = new Mapping();
		Element e = document.getDocumentElement();
		xml2obj(e, mapping);
		// mapping.setNamespace(getAttribute(e, "namespace"));
		// mapping.setPrefix(getAttribute(e, "prefix"));

		MappingWrapper result = new MappingWrapper();
		result.setData(mapping);
		appendModules(result, e);
		return result;
	}

	private static void appendModules(MappingWrapper parent, Element element) {
		NodeList nodeList = element.getElementsByTagName("module");
		List objList = new LinkedList();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element e = (Element) nodeList.item(i);
			Module o = new Module();
			xml2obj(e, o);
			// o.setName(getAttribute(e, "name"));
			// o.setNamespace(getAttribute(e, "namespace"));
			// o.setPrefix(getAttribute(e, "prefix"));
			// o.setTitle(getAttribute(e, "title"));

			ModuleWrapper w = new ModuleWrapper();
			w.setData(o);
			w.setParent(parent);
			appendEntities(w, e);
			objList.add(w);
		}
		parent.setModules(objList);
	}

	private static void appendEntities(ModuleWrapper parent, Element element) {
		NodeList nodeList = element.getElementsByTagName("entity");
		List objList = new LinkedList();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element e = (Element) nodeList.item(i);
			Entity o = new Entity();
			xml2obj(e, o);
			// o.setName(getAttribute(e, "name"));
			// o.setComment(getAttribute(e, "commment"));
			// o.setHasId(getAttribute(e, "has-id"));
			// o.setHasRecord(getAttribute(e, "has-record"));
			// o.setHasStatus(getAttribute(e, "has-status"));
			// o.setPrefix(getAttribute(e, "prefix"));
			// o.setTableName(getAttribute(e, "table"));
			// o.setTitle(getAttribute(e, "title"));

			EntityWrapper w = new EntityWrapper();
			w.setData(o);
			w.setParent(parent);
			appendProperties(w, e);
			objList.add(w);
		}
		parent.setEntities(objList);
	}

	private static void appendProperties(EntityWrapper parent, Element element) {
		NodeList nodeList = element.getElementsByTagName("property");
		List objList = new LinkedList();
		if(parent.getIsAuto()){
			Property o = new Property();
			o.setName("id");
			o.setTitle("主键");
			o.setPropertyType("long");
			o.setIsKey("true");
			o.setSeqName("s_" + parent.getTable());
			PropertyWrapper w = new PropertyWrapper();
			w.setData(o);
			w.setParent(parent);
			objList.add(w);
		}else{
			for (int i = 0; i < nodeList.getLength(); i++) {
				Element e = (Element) nodeList.item(i);
				boolean isKey = getBoolean(e, "is-key", false);
				if(isKey){
					Property o = new Property();
					xml2obj(e, o);
					PropertyWrapper w = new PropertyWrapper();
					w.setData(o);
					w.setParent(parent);
					objList.add(w);
				}
			}
		}
		
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element e = (Element) nodeList.item(i);
			String propertyName = getAttribute(e, "name");
			boolean isKey = getBoolean(e, "is-key", false);
			if(isKey || Utils.isSavedProperty(propertyName)) continue;
			Property o = new Property();
			xml2obj(e, o);
			// o.setName(getAttribute(e, "name"));
			// o.setColumnName(getAttribute(e, "column"));
			// o.setComment(getAttribute(e, "commment"));
			// o.setDefaultValue(getAttribute(e, "default"));
			// o.setDict(getAttribute(e, "dict"));
			// o.setIsKey(getAttribute(e, "is-key"));
			// o.setLength(getLong(e, "length"));
			// o.setIsNotNull(getAttribute(e, "not-null"));
			// o.setPrecision(getLong(e, "precision"));
			// o.setIsQuery(getAttribute(e, "is-query"));
			// o.setReference(getAttribute(e, "ref"));
			// o.setRefProperty(getAttribute(e, "ref-prop"));
			// o.setScale(getLong(e, "scale"));
			// o.setIsShow(getAttribute(e, "is-show"));
			// o.setTitle(getAttribute(e, "title"));
			// o.setPropertyType(getAttribute(e, "type"));
			// o.setIsUnique(getAttribute(e, "unique"));

			PropertyWrapper w = new PropertyWrapper();
			w.setData(o);
			w.setParent(parent);
			objList.add(w);
		}
		if(parent.getIsAuto()){
			Property o = new Property();
			o.setName("status");
			o.setTitle("状态");
			o.setIsNotNull("true");
			o.setDict("yn");
			o.setComment("记录是否有效");
			o.setLength("1");
			o.setIsShow("false");
			PropertyWrapper w = new PropertyWrapper();
			w.setData(o);
			w.setParent(parent);
			objList.add(w);
			addProperty("createdUser", "记录创建人", "long", "true", parent, objList);
			addProperty("createdDate", "记录创建时间", "date", "true", parent, objList);
			addProperty("updatedUser", "记录更新人", "long", null, parent, objList);
			addProperty("updatedDate", "记录更新时间", "date", null, parent, objList);
		}else{
			for (int i = 0; i < nodeList.getLength(); i++) {
				Element e = (Element) nodeList.item(i);
				String propertyName = getAttribute(e, "name");
				boolean isKey = getBoolean(e, "is-key", false);
				if(!isKey && Utils.isSavedProperty(propertyName)){
					Property o = new Property();
					xml2obj(e, o);
					PropertyWrapper w = new PropertyWrapper();
					w.setData(o);
					w.setParent(parent);
					objList.add(w);
				}
			}
		}
		parent.setProperties(objList);
	}
	
	private static void addProperty(String name, String title, String propertyType, String isNotNull, EntityWrapper parent, List objList){
		Property o = new Property();
		o.setName(name);
		o.setTitle(title);
		o.setPropertyType(propertyType);
		o.setIsNotNull(isNotNull);
		o.setIsShow("false");
		PropertyWrapper w = new PropertyWrapper();
		w.setData(o);
		w.setParent(parent);
		objList.add(w);
	}
	
	private static void xml2obj(Element e, Object o) {
		List fields = Utils.getFields(o.getClass());

		for (Iterator iterator2 = fields.iterator(); iterator2.hasNext();) {
			Field field = (Field) iterator2.next();
			String fieldName = field.getName();

			String value = getAttribute(e, Utils.camel2hyphen(fieldName));
			if (value != null) {
				field.setAccessible(true);
				try {
					field.set(o, value);
				} catch (IllegalArgumentException e1) {
					e1.printStackTrace();
				} catch (IllegalAccessException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}

	private static String getAttribute(Element element, String name) {
		if (element != null && element.getAttribute(name) != null
				&& element.getAttribute(name).trim() != "") {
			return element.getAttribute(name).trim();
		} else {
			return null;
		}
	}

	// private static int getType(Element element, String name) {
	// String type = getAttribute(element, name);
	// if (Property.LONG.equalsIgnoreCase(type)) {
	// return Property.TYPE_LONG;
	// }
	// if (Property.DATE.equalsIgnoreCase(type)) {
	// return Property.TYPE_DATE;
	// }
	// if (Property.DOUBLE.equalsIgnoreCase(type)) {
	// return Property.TYPE_DOUBLE;
	// }
	// if (Property.DICT.equalsIgnoreCase(type)) {
	// return Property.TYPE_DICT;
	// }
	// if (Property.REF.equalsIgnoreCase(type)) {
	// return Property.TYPE_REF;
	// }
	// return Property.TYPE_STRING;
	// }

	private static boolean getBoolean(Element element, String name) {
		return getBoolean(element, name, false);
	}

	private static boolean getBoolean(Element element, String name,
			boolean defaultValue) {
		String x = getAttribute(element, name);
		if (StringUtils.isBlank(x))
			return defaultValue;
		return "true".equals(x);
	}

	//
	// private static int getInt(Element element, String name) {
	// return getInt(element, name, 0);
	// }
	//
	// private static int getInt(Element element, String name, int defaultValue)
	// {
	// int i = 0;
	// String x = getAttribute(element, name);
	// if (StringUtils.isBlank(x))
	// return defaultValue;
	// try {
	// i = Integer.parseInt(x);
	// } catch (NumberFormatException e) {
	// log.error("Error int [" + x + "] of name [" + name + "]", e);
	// log.error(e.getMessage(), e);
	// }
	// return i;
	// }

	private static Long string2longObj(String value) {
		Long result = null;
		if (StringUtils.isBlank(value))
			return result;
		try {
			result = new Long(value);
		} catch (NumberFormatException e) {
			log.error("Error long [" + value + "]", e);
			log.error(e.getMessage(), e);
		}
		return result;
	}

	private static Long getLong(Element element, String name) {
		Long result = null;
		String x = getAttribute(element, name);
		if (StringUtils.isBlank(x))
			return result;
		try {
			result = new Long(x);
		} catch (NumberFormatException e) {
			log.error("Error int [" + x + "] of name [" + name + "]", e);
			log.error(e.getMessage(), e);
		}
		return result;
	}

	private static class DocumentBuilderHolder {
		static DocumentBuilder documentBuilder;
		static {
			try {
				documentBuilder = DocumentBuilderFactory.newInstance()
						.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				log.error(e.getMessage(), e);
			} catch (FactoryConfigurationError e) {
				log.error(e.getMessage(), e);
			}
		}
	}

}
